#pragma once

#include <map>
#include <stdint.h>
#include "Buffer.h"
#include "Protocol.h"

enum class OpCode : uint8_t
{
    CONTINUATION = 0,
    TEXT = 1,
    BINARY = 2,
    CLOSE = 8,
    PING = 9,
    PONG = 10
};

struct WebSocketHeader
{
    uint8_t nSize;
    bool bFin;
    bool bMask;
    OpCode opType;
    uint8_t nLen;
    uint64_t nExtLen;
    uint8_t szMask[4];
};

class CWebSocketProt : public CProtocol
{
    typedef std::map<std::string, std::string> HeadersType;

public:
    CWebSocketProt();
    ~CWebSocketProt();

public:
    static CWebSocketProt *WebSocketProtParse(CBuffer<> *pBuffer, PkgBuf *pbRecv, ProtModule &pm);

    int8_t ModuleParse(CBuffer<> *pBuffer, PkgBuf *pbRecv);
    HandleResult DataParse(CBuffer<> *pBuffer, PkgBuf *pbRecv);
    HandleResult DataHandle(PkgBuf *pbRecv, CClient *pClnt);

    bool ProtResponse(PkgBuf *pbSend, bool bResult);
    bool ModuleResponse(PkgBuf *pbSend, bool bResult);

    uint16_t PackageData(uint8_t *pDest, uint8_t *pSrc, uint16_t nLen);

private:
    static char *GetModuleName(char *pBuffer, int &iLen);
    static bool GetHeader(char *pStart, char *pEnd, HeadersType &mapHeader);
    static CWebSocketProt *RequestParse(PkgBuf *pbRecv, ProtModule &pm);

    HandleResult PackageHeaderParse(CBuffer<> *pBuffer, PkgBuf *pbRecv);
    uint16_t PackageData(uint8_t *pDest, OpCode opType, uint8_t *pSrc, uint64_t nLen);

private:
    HeadersType m_mapHeaders;
    WebSocketHeader m_wsHeader;
    static bool m_bMask;
};